home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-12-12 | 51.3 KB | 2,135 lines |
- Newsgroups: comp.sources.misc
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Subject: v09i062: draw, part 02/02
- Reply-To: jta@sah.vtt.fi (Juha Takala)
-
- Posting-number: Volume 9, Issue 62
- Submitted-by: jta@sah.vtt.fi (Juha Takala)
- Archive-name: draw_jt/part02
-
- [This is "dr_lib", a library to produce plots in various formats including
- plot(3) and HPGL formats, and "draw", a simple front-end for the library.
- See the README for more information. ++bsa]
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 2)."
- # Contents: dr_lib.c draw.c
- # Wrapped by allbery@uunet on Tue Dec 12 21:15:58 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'dr_lib.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dr_lib.c'\"
- else
- echo shar: Extracting \"'dr_lib.c'\" \(31312 characters\)
- sed "s/^X//" >'dr_lib.c' <<'END_OF_FILE'
- X/*
- X
- XCopyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; version 1.
- X
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X the file "License" for more details
- X
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- X
- X */
- X
- X
- X/* Description:
- X * dr_lib.c provides interface between device level and my draw(1).
- X * Supported devices are:
- X * - hpgl output for hp7475 plotter
- X * - gl_plot(3) calls for EGA or matrix printer output
- X * - plot(3) interface
- X *
- X */
- Xstatic char *rcsid =
- X "$Id: dr_lib.c,v 2.4 89/12/08 14:00:34 jta Exp Locker: jta $";
- X
- X/* define this, if your plotter connection is 'y-cable' (not direct) */
- X/* #define YCABLE /* */
- X
- X/* definede this if you want to ask paper size from plotter */
- X/* (should not be used, if you are going to use this package as */
- X/* part of pipelines) */
- X/* #define ASK /* */
- X
- X#include <stdio.h>
- X#include <math.h>
- X#ifdef MSDOS
- X#include <bios.h>
- X#endif
- X#include "dr_lib.h"
- X
- X#define ESC 0x1b /* ascii <ESC> */
- X
- Xstatic int xscale(), yscale();
- Xstatic void sends(), invdev();
- X
- X#ifdef ASK
- Xstatic void takes();
- X#endif /* ASK */
- X
- X/*
- X * internal global variable declarations
- X *
- X */
- X /* coordinate transformations */
- Xstatic float xuserincr, yuserincr;
- Xstatic float xuserlow, yuserlow;
- Xstatic float xuserhigh, yuserhigh;
- Xstatic float xdevicelow, ydevicelow;
- Xstatic float xdevicehigh, ydevicehigh;
- Xstatic float xrelarea, yrelarea;
- Xstatic float xfactor, yfactor;
- Xstatic float shape_factor, size_factor; /* text 'fatness' and size factors */
- Xstatic int lastx=0, lasty=0; /* device coordinates for last point */
- X
- X
- Xstatic int device = INVDEV; /* what output device we are working for */
- Xstatic int old_linetype = -1; /* remember last used linetype */
- Xstatic int old_pen = -1; /* ...and pen */
- X
- Xstatic int errcount, warncount, errfile;
- Xstatic char *errfilename = "draw.err";
- X
- Xstatic FILE *errfilefp;
- X
- X
- X
- X/* ********************************************************** */
- X/* */
- X/* Following functions are ment to be subroutines to be */
- X/* called from a user supplied main program */
- X/* */
- X/* ********************************************************** */
- X
- X/*
- X * dr_set_cset() - select cset
- X *
- X */
- Xvoid dr_set_cset(n)
- Xint n;
- X{
- X char s[50];
- X
- X switch (device)
- X {
- X case HP7475:
- X if (n < 0 || n == 5 || (n > 9 && n < 30) || n > 39) {
- X (void)sprintf(s, "Invalid cset code %d, using 0", n);
- X dr_errmsg(s);
- X n = 0;
- X }
- X (void)sprintf(s, "CS%d;\n", n);
- X sends(s);
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X/* (void)sprintf(s, "cset not yet for SCREEN");
- X dr_errmsg(s); /* */
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X/* (void)sprintf(s, "cset not valid for PLOT");
- X dr_errmsg(s); /* */
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X}
- X
- X/*
- X * dr_set_pen() - select pen
- X *
- X */
- Xvoid dr_set_pen(n)
- Xint n; /* pen number, 1..6, 0=='put it away' */
- X{
- X char s[50];
- X
- X switch (device)
- X {
- X case HP7475:
- X if (n < 0 || n > 6) {
- X (void)sprintf(s, "Invalid pen code %d, using 1", n);
- X dr_errmsg(s);
- X n = 1;
- X }
- X if (n != old_pen) { /* optimize for hpgl... */
- X old_pen = n;
- X (void)sprintf(s, "SP%d;", n);
- X sends(s);
- X }
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X/* (void)sprintf(s, "dr_set_pen(colour) not yet for SCREEN\n");
- X dr_errmsg(s); /* */
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X/* (void)sprintf(s, "dr_set_pen(colour) not valid for PLOT\n");
- X dr_errmsg(s); /* */
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X}
- X
- X/*
- X * dr_goto() - move pen to point x, y
- X *
- X */
- Xvoid dr_goto(x, y, penup)
- Xfloat x, y; /* where he wants to go */
- Xint penup; /* nonzero == lift pen before moving */
- X{
- X char s[60];
- X lastx = xscale(x);
- X lasty = yscale(y);
- X switch (device)
- X {
- X case HP7475:
- X if (penup) sends ("PU");
- X else sends ("PA;PD");
- X
- X /* go to point, leave pen as told
- X */
- X (void)sprintf(s, "%d,%d;\n", lastx, lasty);
- X sends(s);
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X if (penup) n_movepen(lastx, lasty);
- X else n_draw(lastx, lasty);
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X if (penup) move(lastx, lasty);
- X else cont(lastx, lasty);
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X return;
- X}
- X
- X
- X/*
- X * dr_draw_line() - draw line (x1,y1) .. (x2,y2)
- X *
- X * connect the two data points with line
- X */
- Xvoid dr_draw_line(x1, y1, x2, y2)
- Xfloat x1, y1, x2, y2; /* data points */
- X{
- X char s[60];
- X
- X lastx = xscale(x2);
- X lasty = yscale(y2);
- X switch (device)
- X {
- X case HP7475:
- X /* lift pen,
- X * go to first point,
- X * drop pen there,
- X */
- X (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x1), yscale(y1));
- X sends(s);
- X
- X /* draw line segment, lift pen
- X */
- X (void)sprintf(s, "PD%d,%d;PU;\n", lastx, lasty);
- X sends(s);
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X n_line(xscale(x1), yscale(y1), lastx, lasty);
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X line(xscale(x1), yscale(y1), lastx, lasty);
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X return;
- X}
- X
- X
- X/*
- X * dr_draw_array() - draw y = f(x)
- X *
- X * connect data points with line
- X */
- Xvoid dr_draw_array(x, y, n)
- Xfloat x[], y[]; /* data points */
- Xint n; /* number of points in x[] and y[] */
- X{
- X int i;
- X char s[60];
- X
- X /* if we really have something to draw
- X */
- X if (n < 1)
- X return;
- X
- X switch (device)
- X {
- X case HP7475:
- X /* lift pen,
- X * go to first point,
- X * drop pen there,
- X */
- X (void)sprintf(s, "PA;PU%d,%d;PD;", xscale(x[0]), yscale(y[0]));
- X sends(s);
- X
- X /* draw line segments
- X */
- X for (i=1; i<n; i++) {
- X if (i % 4 == 0) sends("\n");
- X (void)sprintf(s, "PD%d,%d;", xscale(x[i]), yscale(y[i]));
- X sends(s);
- X }
- X
- X /* finally lift pen
- X */
- X sends("PU;\n");
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X n_movepen(xscale(x[0]), yscale(y[0]));
- X for (i=1; i<n; i++)
- X n_draw(xscale(x[i]), yscale(y[i]));
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X move(xscale(x[0]), yscale(y[0]));
- X for (i=1; i<n; i++)
- X cont(xscale(x[i]), yscale(y[i]));
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X lastx = xscale(x[i-1]);
- X lasty = yscale(y[i-1]);
- X return;
- X}
- X
- X
- X/*
- X * dr_put_mark() - make a mark at (x,y)
- X *
- X * put mark at data point
- X */
- Xvoid dr_put_mark(x, y, mark)
- Xfloat x, y; /* data point */
- Xchar mark;
- X{
- X char s[60];
- X
- X lastx = xscale(x);
- X lasty = yscale(y);
- X switch (device)
- X {
- X case HP7475:
- X /* if we really have something to plot
- X */
- X
- X /* lift pen,
- X * set symbol mode,
- X */
- X (void)sprintf(s, "PA;PU;SM%c;", mark);
- X sends(s);
- X
- X /* put symbol at all data points
- X */
- X (void)sprintf(s, "PU%d,%d;", lastx, lasty);
- X sends(s);
- X
- X /* reset symbol mode
- X */
- X sends("SM;\n");
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X n_movepen(lastx, lasty);
- X n_grafchar(mark);
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X move(lastx, lasty);
- X *s = mark;
- X *(s+1) = '\0';
- X label(s);
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X return;
- X}
- X
- X
- Xvoid dr_set_shape(x)
- Xfloat x;
- X{
- X if (x > 0.0)
- X shape_factor = x * xrelarea/yrelarea;
- X return;
- X}
- X
- X
- Xvoid dr_set_size(x)
- Xfloat x;
- X{
- X if (x > 0.0)
- X size_factor = x;
- X return;
- X}
- X
- X
- X/*
- X * dr_put_text() - put some text
- X * plot(3) only has one size and orientation, what can you do!
- X *
- X */
- Xvoid dr_put_text(x, y, xofs, yofs, angle, size, s)
- Xfloat x, y; /* where to put it */
- Xfloat xofs, yofs; /* offset of start position, measured in */
- X /* character size units */
- Xfloat angle; /* radians, 0.0 == horizontal */
- Xfloat size; /* relative size of text */
- Xchar *s; /* the text */
- X{
- X char ss[60];
- X int senddir;
- X char dir[30];
- X
- X if (size <= 0.0) {
- X sprintf(ss, "invalid size: %f");
- X dr_errmsg(ss);
- X return;
- X }
- X size *= size_factor;
- X
- X switch (device)
- X {
- X case HP7475:
- X senddir = (angle != 0.0);
- X if (senddir) {
- X if (angle == M_PI_2)
- X sprintf(dir,"DI0,1");
- X else if (angle == -M_PI_2)
- X sprintf(dir,"DI0,-1");
- X else
- X sprintf(dir,"DI1,%f", tan(angle));
- X }
- X
- X /* lift pen, go to specified position, set direction & size,
- X */
- X
- X (void)sprintf(ss, "PA;PU%d,%d;%s;SR%4.2f,%4.2f;\n",
- X xscale(x), yscale(y),
- X (senddir ? dir : ""),
- X size * 0.75 * shape_factor * xrelarea,
- X size * 1.5 * yrelarea);
- X sends(ss);
- X
- X /* go to offset,
- X * put text,
- X * restore 0 degree direction.
- X */
- X if ((xofs != 0.0) || (yofs != 0.0)) {
- X (void)sprintf(ss, "CP%4.2f,%4.2f;\n", xofs, yofs);
- X sends(ss);
- X }
- X sends("LB"); sends(s); sends("\03\n");
- X
- X /* correction for y-offset, if necessary, to leave pen on same */
- X /* height but after the text */
- X if (yofs != 0.0) {
- X (void)sprintf(ss, "CP0,%4.2f;\n", -yofs);
- X sends(ss);
- X }
- X
- X if (senddir)
- X sends("DI1,0;\n");
- X/* lastx = ....;
- X lasty = ....; /* hp7475 does not really need these, */
- X /* it remembers the pen position */
- X
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X n_movepen(xscale(x), yscale(y));
- X
- X#define GL_MODE_255_HAS_BUG
- X#ifdef GL_MODE_255_HAS_BUG
- X /* DT Lewis!! Wake up! */
- X /* For some reason gl_lib works strangely with GL_MODE == 255 */
- X /* (the output is (almost) microscopic small and weird shape). */
- X /* We can compensate that strangeness here by modifying size */
- X /* and sape factors for g_fontctl()... The values 3.0 and 0.4 */
- X /* are experimental results (by kekkonen@sah.vtt.fi). */
- X if (strncmp(getenv("GLMODE"),"256",3)==0)
- X g_fontctl(3.0*size*yrelarea, 0.4*shape_factor, 1.0, angle, 0.0);
- X else
- X#endif
- X#undef GL_MODE_255_HAS_BUG
- X g_fontctl(size*yrelarea, shape_factor, 1.0, angle, 0.0);
- X yofs = -0.5 - yofs;
- X n_ch_ofs(xofs, yofs);
- X n_grafstr(s);
- X n_ch_ofs(0.0, -yofs);
- X g_fontctl(size, 1.0, 1.0, 0.0, 0.0);
- X/* lastx = ....;
- X lasty = ....; /* this does not really need these, */
- X /* it remembers the pen position */
- X
- X break;
- X#endif
- X#ifdef PLOT
- X#define PLOT_CH_XSIZE 70
- X#define PLOT_CH_YSIZE 100
- X case PLOTLIB:
- X {
- X int i;
- X float xsize, ysize;
- X float xbase, ybase;
- X float xincr, yincr;
- X float xofs1, yofs1;
- X
- X xsize = PLOT_CH_XSIZE * size * xrelarea;
- X ysize = PLOT_CH_YSIZE * size * yrelarea;
- X
- X yofs += 0.4; /* middle --> botom */
- X xofs1 = (xofs * xsize * cos(angle) * shape_factor -
- X yofs * ysize * sin(angle));
- X yofs1 = (xofs * xsize * sin(angle) * shape_factor +
- X yofs * ysize * cos(angle));
- X xbase = xscale(x) + xofs1;
- X ybase = yscale(y) + yofs1;
- X
- X xincr = cos(angle) * xsize * shape_factor;
- X yincr = sin(angle) * ysize;
- X
- X /* This is how we simulate different printing directions */
- X /* and character sizes: by moving to the position of every */
- X /* single character one at a time */
- X *(ss+1) = '\0';
- X for (i=0; *ss=*s; s++,i) {
- X move((int) (0.5 + xbase + i * xincr),
- X (int) (0.5 + ybase + i * yincr));
- X label(ss);
- X i++;
- X }
- X
- X lastx = (int) (0.5 + xbase + i * xincr - xofs1);
- X lasty = (int) (0.5 + ybase + i * yincr - yofs1);
- X move(lastx, lasty);
- X }
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X return;
- X}
- X
- X/*
- X * dr_small_circle() - draw small circle at current point.
- X * This routine needs the help of lastx and lasty in case of plot(3) library.
- X *
- X */
- Xvoid dr_draw_circle()
- X{
- X switch (device)
- X {
- X case HP7475:
- X sends("CI35;\n"); break;
- X#ifdef GL_LIB
- X case SCREEN:
- X n_ellipse1(100, 100); break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X circle(lastx, lasty, 20); break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X}
- X
- X
- X/*
- X * dr_finish() - terminate the plotting
- X *
- X * This routine must be called after all plotting activity is done
- X * to restore the Y-cable connection so that terminal gets control
- X */
- Xint dr_finish(clean_scr)
- Xint clean_scr; /* != 0 if we have clear screen */
- X{
- X char s[20];
- X
- X switch (device)
- X {
- X case HP7475:
- X /* deselct pen,
- X * reset Y-cable connection
- X * (<esc>.Z is ignored if not Y-cable connecton )
- X */
- X (void)sprintf(s, "SP;%c.Z\n", ESC);
- X sends(s);
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X if (clean_scr && (strncmp(getenv("GLMODE"), "256", 3) != 0)) {
- X#ifdef UNIX
- X FILE *fp = fopen("/dev/tty", "r");
- X fgets(s, 2, fp); /* wait for user response */
- X fclose(fp);
- X#endif /* UNIX */
- X#ifdef MSDOS
- X _bios_keybrd(_KEYBRD_READ); /* wait for keybrd. input forever */
- X#endif /* MSDOS */
- X }
- X {
- X int status;
- X status = g_finish(); /* do clean screen */
- X if (status != 0)
- X dr_errmsg("dr_lib(): problems with g_finish().");
- X }
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X move(0,0);
- X closepl();
- X break;
- X#endif
- X default:
- X break; /* call to invdev() --> recursion */
- X }
- X
- X /* check errors, tell if any or remove error log file
- X */
- X if (errcount == 0 && warncount == 0)
- X (void)unlink(errfilename);
- X else {
- X if (errcount)
- X (void)fprintf(stderr, "%d error%s,",
- X errcount, (errcount == 1 ? "" : "s"));
- X if (warncount)
- X (void)fprintf(stderr, "%d warning%s,",
- X warncount, (warncount == 1 ? "" : "s"));
- X (void)fprintf (stderr, " see file \"%s\".\n", errfilename);
- X }
- X /* return something useful
- X */
- X return (errcount);
- X}
- X
- X
- X/*
- X * dr_start - init the plotting device
- X *
- X * This routine must be called before any plotting activity is done
- X * to set up the Y-cable connction so that plotter starts processing
- X * or in case of direct connection, open the device
- X */
- Xvoid dr_start(xlow, ylow, xhigh, yhigh, dev)
- Xint dev; /* plotting device & paper size */
- Xfloat xlow, xhigh; /* drawing area, relative to.. */
- Xfloat ylow, yhigh; /* ..whole paper, that means: */
- X /* 0.0, 0.5, 0.5, 1.0 will use */
- X /* upper left quarter of paper */
- X{
- X int p1x, p1y, p2x, p2y;
- X float t1, t2;
- X char s[200];
- X
- X /* open error log file
- X */
- X errcount = 0;
- X warncount = 0;
- X if ((errfilefp = fopen(errfilename, "w")) == NULL) {
- X (void)fprintf(stderr, "\nCan't open %s. Aborting.\n", errfilename);
- X exit(1);
- X }
- X errfile = fileno(errfilefp);
- X xrelarea = xhigh - xlow;
- X yrelarea = yhigh - ylow;
- X shape_factor = yrelarea/xrelarea; /* back to normal 'fatness' */
- X size_factor = 1.0; /* actual size normalized to area */
- X
- X switch (device = (dev & DEVMASK))
- X {
- X case HP7475:
- X /* set Y-cable connection,
- X * (<esc>.Y is ignored if not Y-cable connecton )
- X * init the plotter,
- X * set handshake mode x-on/x-off,
- X * select pen #1
- X */
- X (void)sprintf(s, "\n%c.Y;IN;", ESC); /* Y-connection, plotter on */
- X sends(s);
- X (void)sprintf(s, "%c.I80;;17:", ESC); /* enable x-on/x-off x-on=^q */
- X sends(s);
- X (void)sprintf(s, "%c.N;19:\n", ESC); /* x-off=^s */
- X sends(s);
- X#ifdef ASK
- X /* ask picture area from plotter
- X * set up limits (leave some room for axis labels etc.) */
- X sends("OP;");
- X takes(s);
- X#else /* ASK */
- X /* we would get one of this */
- X switch (dev & SIZEMASK)
- X {
- X case SIZE_A:
- X (void)sprintf (s, "250,596,10250,7796\n");
- X sends("PS4;\n");
- X break;
- X case SIZE_A4:
- X (void)sprintf (s, "603,521,10603,7721\n");
- X sends("PS4;\n");
- X break;
- X case SIZE_B:
- X (void)sprintf (s, "522,259,15722,10259\n");
- X sends("PS3;\n");
- X break;
- X case SIZE_A3:
- X (void)sprintf (s, "170,602,15370,10602\n");
- X sends("PS3;\n");
- X break;
- X default:
- X dr_errmsg("Invalid paper size. Aborting.");
- X (void)dr_finish();
- X exit(1);
- X }
- X#endif /* ASK */
- X if ( sscanf(s, "%d,%d,%d,%d", &p1x, &p1y, &p2x, &p2y) == 4 ) {
- X /* some room for labels */
- X t1 = p1x + 0.05*(p2x-p1x); /* y-label */
- X t2 = p2x - 0.001*(p2x-p1x); /* right margin */
- X xdevicelow = t1 + xlow * (t2 - t1);
- X xdevicehigh = t1 + xhigh * (t2 - t1);
- X t1 = p1y + 0.05*(p2y-p1y); /* x-label */
- X t2 = p2y - 0.07*(p2y-p1y); /* name */
- X ydevicelow = t1 + ylow * (t2 - t1);
- X ydevicehigh = t1 + yhigh * (t2 - t1);
- X }
- X else {
- X dr_errmsg("Can't receive plotter dimensions. Aborting.");
- X (void) dr_finish();
- X exit(1);
- X }
- X
- X dr_set_pen(1); /* select some pen */
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X p1x = 0; p1y = 32767;
- X p2x = 32767; p2y = 0;
- X t1 = p1x + 0.06*(p2x-p1x); /* room y-axis label */
- X t2 = p2x - 0.001*(p2x-p1x); /* no room at right margin */
- X xdevicelow = t1 + xlow * (t2 - t1);
- X xdevicehigh = t1 + xhigh * (t2 - t1);
- X t1 = p1y + 0.10*(p2y-p1y); /* room for x-axis label */
- X t2 = p2y - 0.05*(p2y-p1y); /* room fo picture's name */
- X ydevicelow = t1 + ylow * (t2 - t1);
- X ydevicehigh = t1 + yhigh * (t2 - t1);
- X
- X#define ENV_MODE 0 /* from gl.h; it means that g_init() will */
- X /* look operating mode in environment */
- X /* variable GLMODE */
- X g_init(ENV_MODE);
- X#undef ENV_MODE
- X /* dr_set_pen(1); /* select some pen */
- X break;
- X#endif
- X
- X#ifdef PLOT
- X case PLOTLIB:
- X /* Y-cable for Tektornix? */
- X p1x = 0; p1y = 0;
- X p2x = 5450; p2y = 4095;
- X /* 5% room for labels */
- X t1 = p1x + 0.07*(p2x-p1x); /* y-label */
- X t2 = p2x - 0.02*(p2x-p1x);; /* righ margin */
- X xdevicelow = t1 + xlow * (t2 - t1);
- X xdevicehigh = t1 + xhigh * (t2 - t1);
- X t1 = p1y + 0.10*(p2y-p1y); /* x-label */
- X t2 = p2y - 0.05*(p2y-p1y); /* name */
- X ydevicelow = t1 + ylow * (t2 - t1);
- X ydevicehigh = t1 + yhigh * (t2 - t1);
- X
- X openpl();
- X space(0,0,4096,4096);
- X erase();
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X
- X /* check coordinate position legality
- X */
- X if (xlow < -0.0001 || xhigh > 1.0001 ||
- X ylow < -0.0001 || yhigh > 1.0001) {
- X dr_errmsg("Illegal x/y low/high position. Aborting.");
- X (void)dr_finish();
- X exit(1);
- X }
- X return;
- X}
- X
- X
- X/*
- X * dr_xgrid - draw x grid
- X *
- X * Draw grid lines parallel to y-axis. When argument n == 0, makes
- X * lines at every tic-mark, n == 1 makes one grid line between every
- X * tic mark etc. To leave grid lines away, just don't call this.
- X */
- Xvoid dr_xgrid(n)
- Xint n; /* number of grid lines */
- X /* between tic-marks */
- X{
- X int i;
- X int x, y1, y2; /* temps for grid line positions */
- X int nlines; /* number of grid lines to draw */
- X char s[200];
- X
- X /* check interval
- X */
- X if (n < 1) {
- X dr_errmsg("Invalid x-grid interval, using 1");
- X n = 1;
- X }
- X
- X /* how many lines we have?
- X */
- X nlines = (int) (n*(xuserhigh-xuserlow)/xuserincr - 0.5);
- X
- X switch (device)
- X {
- X case HP7475:
- X /* select absolute moving
- X */
- X sends("PA;\n");
- X#ifdef SLOW
- X if (slow) {
- X }
- X#endif
- X /* draw desired number of lines, sawing up and down
- X */
- X y1 = yscale(yuserlow);
- X y2 = yscale(yuserhigh);
- X for (i=1; i<=nlines; i++) {
- X /* go up */
- X x = xscale(i*xuserincr/n+xuserlow);
- X (void)sprintf(s, "PU%d,%d;PD%d,%d;", x, y1, x, y2);
- X sends(s);
- X /* go down */
- X if (++i <= nlines) {
- X x = xscale(i*xuserincr/n+xuserlow);
- X (void)sprintf(s, "PU%d,%d;PD%d,%d;\n", x, y2, x, y1);
- X sends(s);
- X }
- X }
- X
- X /* lift pen
- X */
- X sends("PU;\n");
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X y1 = yscale(yuserlow);
- X y2 = yscale(yuserhigh);
- X for (i=1; i<=nlines; i++) {
- X x = xscale(i*xuserincr/n+xuserlow);
- X n_line(x,y1, x,y2);
- X }
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X y1 = yscale(yuserlow);
- X y2 = yscale(yuserhigh);
- X for (i=1; i<=nlines; i++) {
- X x = xscale(i*xuserincr/n+xuserlow);
- X line(x,y1, x,y2);
- X }
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X}
- X
- X
- X/*
- X * dr_ygrid - draw y grid
- X *
- X * See dr_xgrid().
- X */
- Xvoid dr_ygrid(n)
- Xint n;
- X{
- X int i;
- X int nlines; /* number of lines */
- X char s[200];
- X int x1, x2, y;
- X
- X /* check interval
- X */
- X if (n < 1) {
- X dr_errmsg("Invalid y-grid interval, using 1");
- X n = 1;
- X }
- X
- X /* how many lines do we have?
- X */
- X nlines = (int) (n*(yuserhigh-yuserlow)/yuserincr - 0.5);
- X
- X switch (device)
- X {
- X case HP7475:
- X /* select absolute moving
- X */
- X sends("PA;\n");
- X
- X /* draw desired number of lines, sawing right and left
- X */
- X x1 = xscale(xuserlow);
- X x2 = xscale(xuserhigh);
- X for (i=1; i<=nlines; i++) {
- X /* go right */
- X y = yscale(yuserlow+i*yuserincr/n);
- X (void)sprintf(s, "PU%d,%d;PD%d,%d;", x1, y, x2, y);
- X sends(s);
- X /* go left */
- X if (++i <= nlines) {
- X y = yscale(yuserlow+i*yuserincr/n);
- X (void)sprintf(s, "PU%d,%d;PD%d,%d;", x2, y, x1, y);
- X sends(s);
- X }
- X sends("\n");
- X }
- X
- X /* lift pen
- X */
- X sends("PU;\n");
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X x1 = xscale(xuserlow);
- X x2 = xscale(xuserhigh);
- X for (i=1; i<=nlines; i++) {
- X y = yscale(i*yuserincr/n+yuserlow);
- X n_line(x1,y, x2,y);
- X }
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X x1 = xscale(xuserlow);
- X x2 = xscale(xuserhigh);
- X for (i=1; i<=nlines; i++) {
- X y = yscale(i*yuserincr/n+yuserlow);
- X line(x1,y, x2,y);
- X }
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X}
- X
- X
- X/*
- X * dr_area_def - establish x and y axis
- X *
- X * [xy]low lower left corner
- X * [xy]high upper right corner
- X * [xy]incr increment of tic-marks
- X * no_axes flag, != 0 means don't draw axes
- X *
- X * Coordinate values will be printed at every tic-mark, so useful
- X * values for incr is such that (high-low)/incr will be some small
- X * integer. With functions dr_xgrid() and dr_ygrid() it is possible to
- X * draw grid lines also in between these tic-marcs.
- X */
- Xvoid dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes)
- Xfloat xlow, xincr, xhigh;
- Xfloat ylow, yincr, yhigh;
- Xint no_axes;
- X{
- X int i;
- X char units[30]; /* place for units */
- X char s[200];
- X float x, y;
- X int ix, iy, nx, ny;
- X
- X /* set the globals
- X */
- X xuserlow = xlow; xuserhigh = xhigh; xuserincr = xincr;
- X yuserlow = ylow; yuserhigh = yhigh; yuserincr = yincr;
- X xfactor = (xdevicehigh - xdevicelow) / (xuserhigh - xuserlow);
- X yfactor = (ydevicehigh - ydevicelow) / (yuserhigh - yuserlow) ;
- X
- X /* check legality,
- X * abort on error
- X */
- X if ((xincr == 0.0) ||
- X (xuserlow == xuserhigh) ||
- X ((xuserhigh-xuserlow)*xincr < 0.0)) {
- X dr_errmsg("x-axis defined improperly. Aborting.");
- X (void)dr_finish();
- X exit(1);
- X }
- X if ((yincr == 0.0) ||
- X (yuserlow == yuserhigh) ||
- X ((yuserhigh-yuserlow)*yincr < 0.0)) {
- X dr_errmsg("y-axis defined improperly. Aborting.");
- X (void)dr_finish();
- X exit(1);
- X }
- X if (no_axes)
- X return;
- X
- X switch (device)
- X {
- X case HP7475:
- X
- X /* draw box
- X * --------
- X */
- X
- X /* select absolute plotting mode,
- X * lift pen,
- X * go to lower left corner
- X */
- X (void)sprintf(s,"PA;PU%d,%d;\n",
- X xscale(xlow), yscale(ylow));
- X sends(s);
- X
- X /* draw x-axis with x-tick marks
- X */
- X
- X (void)sprintf(s, "TL%.1f,%.1f;\n", 0.5*xrelarea, 0.5*yrelarea);
- X sends(s);
- X for (nx=0, x = xlow;
- X x < xhigh + xincr/100.0;
- X x += xincr, nx++) {
- X (void)sprintf(s, "PD%d,%d;XT;\n", xscale(x), yscale(ylow));
- X sends(s);
- X }
- X (void)sprintf(s, "PD%d,%d;\n", xscale(xhigh), yscale(ylow));
- X sends(s);
- X
- X /* draw y-axis with y-tick marks
- X */
- X (void)sprintf(s, "PU%d,%d;\n",
- X xscale(xlow), yscale(ylow));
- X sends(s);
- X for (ny=0, y = ylow;
- X y < yhigh + yincr/100.0;
- X y += yincr, ny++) {
- X (void)sprintf(s, "PD%d,%d;YT;\n", xscale(xlow), yscale(y));
- X sends(s);
- X }
- X (void)sprintf(s, "PD%d,%d;\n", xscale(xlow), yscale(yhigh));
- X sends(s);
- X
- X /* outer borders of the box
- X */
- X (void)sprintf(s, "PU%d,%d;PD%d,%d,%d,%d;PU\n",
- X xscale(xlow), yscale(yhigh),
- X xscale(xhigh), yscale(yhigh),
- X xscale(xhigh), yscale(ylow));
- X sends(s);
- X break;
- X#ifdef GL_LIB
- X#define GL_TIC_SIZE 200
- X case SCREEN:
- X iy = yscale(ylow);
- X n_movepen(xscale(xlow), iy);
- X
- X for (nx=0, x = xlow;
- X x < xhigh + xincr/100.0;
- X x += xincr, nx++) {
- X ix = xscale(x);
- X n_draw(ix, iy);
- X n_line(ix, iy+GL_TIC_SIZE, ix, iy-GL_TIC_SIZE);
- X n_movepen(ix, iy);
- X }
- X n_draw(xscale(xhigh), iy);
- X
- X /* draw y-axis with y-tick marks
- X */
- X ix = xscale(xlow);
- X n_movepen(ix, yscale(ylow));
- X for (ny=0, y = ylow;
- X y < yhigh + yincr/100.0;
- X y += yincr, ny++) {
- X iy = yscale(y);
- X n_draw(ix, iy);
- X n_line(ix+GL_TIC_SIZE, iy, ix-GL_TIC_SIZE, iy);
- X n_movepen(ix, iy);
- X }
- X n_draw(ix, yscale(yhigh));
- X
- X /* outer borders of the box
- X */
- X n_movepen(xscale(xlow), yscale(yhigh));
- X n_draw(xscale(xhigh), yscale(yhigh));
- X n_draw(xscale(xhigh), yscale(ylow));
- X break;
- X#endif
- X#ifdef PLOT
- X#define PLOT_TIC_SIZE 40
- X case PLOTLIB:
- X iy = yscale(ylow);
- X move(xscale(xlow), iy);
- X
- X for (nx=0, x = xlow;
- X x < xhigh + xincr/100.0;
- X x += xincr, nx++) {
- X ix = xscale(x);
- X cont(ix, iy);
- X line(ix, iy+PLOT_TIC_SIZE, ix, iy-PLOT_TIC_SIZE);
- X move(ix, iy);
- X }
- X cont(xscale(xhigh), iy);
- X
- X /* draw y-axis with y-tick marks
- X */
- X ix = xscale(xlow);
- X move(ix, yscale(ylow));
- X for (ny=0, y = ylow;
- X y < yhigh + yincr/100.0;
- X y += yincr, ny++) {
- X iy = yscale(y);
- X cont(ix, iy);
- X line(ix+PLOT_TIC_SIZE, iy, ix-PLOT_TIC_SIZE, iy);
- X move(ix, iy);
- X }
- X cont(ix, yscale(yhigh));
- X
- X /* outer borders of the box
- X */
- X move(xscale(xlow), yscale(yhigh));
- X cont(xscale(xhigh), yscale(yhigh));
- X cont(xscale(xhigh), yscale(ylow));
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X
- X
- X /* put y-units
- X */
- X for (i=ny-1; i>=0; i--) {
- X (void)sprintf(units, "%g", ylow + i * yincr);
- X dr_put_text(xlow, ylow+i*yincr,
- X -strlen(units)/2.0, -1.3, -M_PI_2, 1.0, units);
- X }
- X
- X /* put x-units
- X */
- X for (i=0; i<nx; i++) {
- X (void)sprintf(units, "%g", xlow + i * xincr);
- X dr_put_text(xlow+i*xincr, ylow,
- X -strlen(units)/2.0, -1.3, 0.0, 1.0, units);
- X }
- X return;
- X}
- X
- X/*
- X * linetypes
- X *
- X */
- X#ifdef GL_LIB
- Xstatic long gl_line_types[] = { /* 76543210765432107654321076543210 */
- X 0xf0000000L, /* ====............................ */
- X 0xffff0000L, /* ================................ */
- X 0xffffff00L, /* ========================........ */
- X 0xffffff18L, /* ========================...==... */
- X 0xfffff0f0L, /* ====================....====.... */
- X 0xfffff39cL, /* ====================..===..===.. */
- X 0xffffffffL, /* ================================ */
- X 0x66666666L, /* ==..==..==..==..==..==..==..==.. */
- X 0xf8f8f8f8L, /* =====...=====...=====...=====... */
- X 0xffffff00L, /* ========================........ */
- X 0xfc30fc30L }; /* ======....==....======....==.... */
- X#define DEF_GL_TYPE 7 /* this will produce continous line */
- X#endif /* GL_PLOT */
- X#ifdef PLOT
- Xstatic char *plot_line_types[] = {
- X "dotted", /* 1 */
- X "longdashed", /* 2 */
- X "shortdashed", /* 3 */
- X "dotdashed", /* 4 */
- X "solid", /* 5 */
- X "solid", /* 6 */
- X "solid" }; /* 7 */
- X#define DEF_PLOT_TYPE 7 /* this will produce continous line */
- X#endif /* PLOT */
- X
- Xint dr_set_ltype(linetype)
- Xint linetype;
- X{
- X char s[40];
- X int old_val = old_linetype;
- X
- X switch (device)
- X {
- X case HP7475:
- X if (linetype < 0 || linetype > 6) {
- X linetype = 7;
- X sends("LT;");
- X }
- X else {
- X (void)sprintf(s, "LT%d;", linetype);
- X sends(s);
- X }
- X break;
- X#ifdef GL_LIB
- X case SCREEN:
- X if (linetype < 1 ||
- X linetype > (sizeof(gl_line_types) / sizeof(gl_line_types[0]))) {
- X sprintf (s, "Invalid linetype: %d", linetype);
- X dr_errmsg(s);
- X linetype = DEF_GL_TYPE;
- X }
- X g_style(gl_line_types[linetype-1]);
- X break;
- X#endif
- X#ifdef PLOT
- X case PLOTLIB:
- X if (linetype < 1 ||
- X linetype > (sizeof(plot_line_types) /
- X sizeof(plot_line_types[0]))) {
- X sprintf (s, "Invalid linetype: %d", linetype);
- X dr_errmsg(s);
- X linetype = DEF_PLOT_TYPE;
- X }
- X linemod(plot_line_types[linetype-1]);
- X break;
- X#endif
- X default:
- X invdev(); break;
- X }
- X old_linetype = linetype;
- X return old_val;
- X}
- X
- X/*
- X * xscale - scaling in horizontal directon
- X *
- X * convert user x-coordinate to physical device x-coordinate
- X */
- Xstatic int xscale(x)
- Xfloat x;
- X{
- X int temp;
- X char s[60];
- X
- X /* calculate it
- X */
- X temp = (int) ((x - xuserlow) * xfactor + xdevicelow + 0.5);
- X /* check, if it is good
- X */
- X if ((temp >= -32768) && (temp <= 32767))
- X return (temp);
- X
- X /* when not good make report,
- X * return something
- X */
- X (void)sprintf(s, "x-value out of range: %f", x);
- X dr_warnmsg(s);
- X return (int) (xdevicelow + 0.5);
- X}
- X
- X
- X/*
- X * yscale - scaling in vertical directon
- X *
- X * convert user y-coordinate to physical device y-coordinate
- X */
- Xstatic int yscale(y)
- Xfloat y;
- X{
- X int temp;
- X char s[60];
- X
- X /* calculate it
- X */
- X temp = (int) ((y - yuserlow) * yfactor + ydevicelow + 0.5);
- X
- X /* check, if it is good
- X */
- X if ((temp >= -32768) && (temp <= 32767))
- X return (temp);
- X
- X /* when not good make report,
- X * return something
- X */
- X (void)sprintf(s, "y-value out of range: %f", y);
- X dr_warnmsg(s);
- X return (int) (ydevicelow + 0.5);
- X}
- X
- Xstatic void invdev()
- X{
- X dr_errmsg("Invalid plotting device.");
- X (void)dr_finish();
- X exit(1);
- X}
- X
- X
- X/*
- X * dr_errmsg - send a string to error output
- X *
- X */
- Xvoid dr_errmsg(s)
- Xchar *s;
- X{
- X char *p = s + strlen(s);
- X if (p != s) p--;
- X while ((p != s) && (*p == '\n')) /* strip the newlines */
- X *(p--) = '\0';
- X fprintf(errfilefp, "dr_lib error: %s\n", s);
- X errcount++;
- X return;
- X}
- X
- X
- X/*
- X * warnmsg - send a string to error output
- X *
- X */
- Xvoid dr_warnmsg(s)
- Xchar *s;
- X{
- X char *p = s + strlen(s);
- X if (p != s) p--;
- X while ((p != s) && (*p == '\n')) *(p--) = '\0';
- X fprintf(errfilefp, "Warning: %s\n", s);
- X warncount++;
- X return;
- X}
- X
- X
- X/*
- X * sends - send something to plotting device
- X *
- X */
- Xstatic void sends(s)
- Xchar *s;
- X{
- X (void)printf("%s", s);
- X}
- X
- X#ifdef ASK
- X/*
- X * takes - take a string from plotter (to read plotter coordinates)
- X *
- X */
- X#include <signal.h>
- X#include <setjmp.h>
- X
- Xjmp_buf sjbuf;
- Xint (*savAlrm)(); /* save incomming alarm function */
- X
- Xstatic int timerh() /* timer interrupt handler */
- X{
- X longjmp(sjbuf, 1);
- X}
- X
- Xstatic void takes(s)
- Xchar *s;
- X{
- X#ifdef YCABLE
- X savAlrm = signal(SIGALRM,timerh);
- X alarm(2); /* give time to wake up */
- X if (setjmp(sjbuf)) {
- X alarm(0);
- X signal(SIGALRM,savAlrm); /* cancel timer */
- X (void)dr_finish();
- X (void)fprintf(stderr, "\n\7Timeout reading stdin. Aborting.\n");
- X exit(1);
- X }
- X gets(s);
- X alarm(0);
- X signal(SIGALRM,savAlrm); /* cancel timer */
- X#else
- X /* do it yorself */
- X#endif
- X}
- X#endif /* ASK */
- END_OF_FILE
- if test 31312 -ne `wc -c <'dr_lib.c'`; then
- echo shar: \"'dr_lib.c'\" unpacked with wrong size!
- fi
- # end of 'dr_lib.c'
- fi
- if test -f 'draw.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'draw.c'\"
- else
- echo shar: Extracting \"'draw.c'\" \(17080 characters\)
- sed "s/^X//" >'draw.c' <<'END_OF_FILE'
- X/*
- X
- XCopyright (C) 1988, 1989 by Juha Takala, jta@sah.vtt.fi
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; version 1.
- X
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X the file "License for more details
- X
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X
- X
- X */
- X
- X/* Description:
- X * Non-interactive user interface program to provide interface between
- X * device manipulation subroutines and user supplied command files.
- X * This program will accept all kinds of command line arguments and
- X * pseudo comments mixed in between the data lines. See the man page.
- X *
- X * The good thing about this program is that it will accept infinite
- X * amount of input data points; they are not stored, but processed one
- X * at a time.
- X */
- Xstatic char *RCS_id =
- X "$Id: draw.c,v 2.7 89/12/08 14:00:39 jta Exp Locker: jta $";
- X
- X#include <stdio.h>
- X#ifdef MSDOS
- X#include <stdlib.h>
- X#endif /* MSDOS */
- X#include <string.h>
- X#include <sys/types.h>
- X#include <time.h>
- X#include <math.h>
- X#include <signal.h>
- X#ifndef MSDOS
- X#include <sys/inode.h>
- X#include <sys/file.h>
- X#endif
- X#include <string.h>
- X#include "dr_lib.h"
- X
- Xdouble strtod();
- X
- Xchar *myname;
- Xfloat xlowl = 0.0; /* relative plotting area on paper */
- Xfloat ylowl = 0.0;
- Xfloat xhighr= 1.0;
- Xfloat yhighr = 1.0;
- X
- Xfloat xlow = -1.0; /* x axis range */
- Xfloat xincr = 0.5;
- Xfloat xhigh = 1.0;
- Xint xgrid_n = 0;
- Xchar *xlabel_text = NULL;
- X
- Xfloat ylow = -1.0; /* y axis range */
- Xfloat yincr = 0.5;
- Xfloat yhigh = 1.0;
- Xint ygrid_n = 0;
- Xchar *ylabel_text = NULL;
- X
- Xstatic float x, y; /* current point, needs to be */
- X /* remembered, eg. when relative text is */
- X /* inserted by #$texthere */
- Xchar *name_text = NULL; /* name of picture */
- Xint pennum = 1;
- Xint penup = 1;
- Xint no_axes = 0;
- Xint init_done = 0;
- Xint dateflag = 0;
- Xint linetype = 7; /* default for solid linetype */
- Xfloat text_angle = 0.0; /* radians */
- Xfloat text_size = 1.0; /* text size factor */
- Xfloat text_shape = 1.0; /* text shape factor */
- Xint cset = 0; /* char set, default is US Ascii */
- Xint continuous = 1; /* continuous line / discrete points */
- X /* 0 = discontinous */
- Xchar marker = '*'; /* default marker char in discontinous mode */
- Xchar informat[200] = "%f %f"; /* default input data line format */
- Xint reversed = 0; /* != 0 means input is y before x */
- Xint absolute = 0; /* != 0 when 'absolute' coordinates are */
- X /* to be processed */
- Xfloat xabs_origin = 0.0; /* origin of 'absolute' mode data points */
- Xfloat yabs_origin = 0.0;
- X
- Xint device = HP7475 | SIZE_A4;
- X
- Xstatic int setmode();
- Xstatic int labelpic();
- Xstatic void doit();
- Xstatic void setdevice();
- Xextern void exit();
- X
- Xstatic void (*old_int_handler)();
- Xstatic void new_int_handler();
- Xstatic void fatal();
- Xstatic void usage();
- X
- X#define PUT_TEXT(x,y,xofs,yofs,text) \
- X dr_put_text((x), (y), (xofs), (yofs), text_angle, 1.0, (text))
- X#define PUT_X_TEXT(x,y,text) \
- X dr_put_text((x), (y), -(float)strlen(text), -2.0, 0.0, 1.4, (text))
- X#define PUT_Y_TEXT(x,y,text) \
- X dr_put_text((x), (y), 0.0, -2.0, -M_PI_2, 1.4, (text))
- X#define PUT_N_TEXT(x,y,text) \
- X dr_put_text((x), (y), -(float)strlen(text)/2.0, 0.4, 0.0, 2.0, (text))
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int c;
- X extern char *optarg;
- X extern int optind, opterr;
- X char *opts = "a:bc:df:g:hl:m:n:p:s:S:t:x:X:y:Y:v";
- X
- X FILE *fp;
- X
- X myname = *argv;
- X setdevice(getenv("DRAWDEV"));
- X
- X
- X while ((c = getopt(argc, argv, opts)) != -1) {
- X switch (c) {
- X case 'a':
- X if (sscanf(optarg, "%f,%f,%f,%f",
- X &xlowl, &ylowl, &xhighr, &yhighr) != 4)
- X fatal("invalid plotting area definition: ", optarg);
- X break;
- X case 'b': no_axes++; break;
- X case 'c': cset = atoi(optarg); break;
- X case 'd': dateflag++; break;
- X case 'f':
- X /* input lines are : "-- -- y -- -- x -- --"
- X * (dashes indicate fields, that we are not interested in)
- X * and we want to plot y=f(x), so we specify option
- X * "-f 6,3" (fields are numbered from 1...)
- X */
- X {
- X int xcol, ycol;
- X if (sscanf(optarg, "%d,%d", &xcol, &ycol) != 2)
- X fatal("invalid input format definition: %s", optarg);
- X if (xcol == ycol)
- X fatal("invalid input format definition: %s", optarg);
- X if (xcol > ycol) {
- X int temp = xcol;
- X reversed++;
- X xcol = ycol;
- X ycol = temp;
- X }
- X ycol -= xcol;
- X informat[0] = '\0';
- X while (--xcol)
- X (void)strcat(informat, "%*f ");
- X (void)strcat(informat, "%f ");
- X while (--ycol)
- X (void)strcat(informat, "%*f ");
- X (void)strcat(informat, "%f");
- X }
- X break;
- X case 'g':
- X if (sscanf(optarg, "%d,%d", &xgrid_n, &ygrid_n) != 2)
- X fatal("invalid grid spec.: ", optarg);
- X break;
- X case 'h': case '?':
- X usage(); break;
- X case 'l':
- X if (sscanf(optarg, "%d", &linetype) != 1)
- X fatal("invalid line type:", optarg);
- X break; /* draw axes before setting it! */
- X case 'm':
- X continuous = 0;
- X if (sscanf(optarg, "%1s", &marker) != 1)
- X fatal ("no marker found.", "\0");
- X break;
- X case 'n':
- X name_text = optarg; break;
- X case 'p':
- X if (sscanf(optarg, "%d", &pennum) != 1)
- X fatal("invalid pen:", optarg);
- X if ((pennum > 6) || (pennum < 1))
- X pennum = 1;
- X break;
- X case 's':
- X if (sscanf(optarg, "%f", &text_size) != 1)
- X fatal("invalid text size: ", optarg);
- X break;
- X case 'S':
- X if (sscanf(optarg, "%f", &text_shape) != 1)
- X fatal("invalid text shape: ", optarg);
- X break;
- X case 't': setdevice(optarg); break;
- X case 'x':
- X if (sscanf(optarg, "%f,%f,%f",
- X &xlow, &xincr, &xhigh) != 3)
- X fatal("invalid x range: ", optarg);
- X break;
- X case 'X':
- X xlabel_text = optarg; break;
- X case 'y':
- X if (sscanf(optarg, "%f,%f,%f",
- X &ylow, &yincr, &yhigh) != 3)
- X fatal("invalid y range: ", optarg);
- X break;
- X case 'Y':
- X ylabel_text = optarg; break;
- X case 'v':
- X fprintf(stderr, "%s\n", RCS_id);
- X exit (0);
- X default:
- X exit(1);
- X }
- X }
- X argc -= optind;
- X argv += optind;
- X
- X old_int_handler = signal (SIGINT, new_int_handler);
- X
- X /*
- X * Options have been taken, start the work. Initializations will be
- X * done just before first data point is used... This is jippo to
- X * make it possible to give coordinate specifications from inside
- X * the data....
- X */
- X if (argc == 0) /* no files, take points from stdin */
- X doit(stdin);
- X else { /* take points from all files */
- X for ( ; argc; argc--, argv++) {
- X if (NULL == (fp = fopen(*argv, "r"))) {
- X perror(*argv);
- X continue;
- X }
- X doit(fp);
- X fclose(fp);
- X }
- X }
- X if (init_done)
- X return(dr_finish(1) ? 1 : 0); /* 1 == error(s) */
- X else
- X return 2; /* nothing was done! */
- X}
- X
- X
- X/* gl_plot will set int handler at its initialization time, and restore
- X what it saw there previously, and finally it will
- X kill(SIGINT,getpid()). This is what we are going to do, too, so that
- X OUR caller can clean ITS data stuctures etc.
- X*/
- Xstatic void new_int_handler() {
- X (void)dr_finish(0);
- X signal (SIGINT, old_int_handler);
- X kill (getpid(), SIGINT); /* zap my self */
- X sleep(1);
- X exit(3); /* if that is not enough */
- X}
- X
- X
- Xstatic void do_initializations()
- X{
- X init_done++; /* remember it is done */
- X dr_start(xlowl, ylowl, xhighr, yhighr, device);
- X if (cset != 0) dr_set_cset(cset);
- X dr_set_size(text_size);
- X dr_set_shape(text_shape);
- X dr_set_pen(pennum);
- X dr_area_def(xlow, xincr, xhigh, ylow, yincr, yhigh, no_axes);
- X if (!no_axes) {
- X if (xgrid_n) dr_xgrid(xgrid_n);
- X if (ygrid_n) dr_ygrid(ygrid_n);
- X }
- X if (xlabel_text) PUT_X_TEXT(xhigh, ylow, xlabel_text);
- X if (ylabel_text) PUT_Y_TEXT(xlow, yhigh, ylabel_text);
- X if (name_text) PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, name_text);
- X if (dateflag) putdate(dateflag);
- X dr_set_ltype(linetype);
- X}
- X
- Xstatic void setdevice(s)
- Xchar *s;
- X{
- X if (s == NULL) return;
- X if (!strcmp(s,"a4")) device = (HP7475 | SIZE_A4);
- X else if (!strcmp(s,"a3")) device = (HP7475 | SIZE_A3);
- X else if (!strcmp(s,"a")) device = (HP7475 | SIZE_A);
- X else if (!strcmp(s,"b")) device = (HP7475 | SIZE_B);
- X#ifdef GL_LIB
- X else if (!strcmp(s,"ega")) device = SCREEN;
- X#endif
- X#ifdef PLOT
- X else if (!strcmp(s,"plot")) device = PLOTLIB;
- X#endif
- X#ifdef TEK
- X else if (!strcmp(s,"tek"))
- X fatal("Sorry,", "Tek4010 not yet.");
- X#endif
- X else fatal("Unsupported plotting device", s);
- X}
- X
- Xstatic void doit(fp)
- XFILE *fp;
- X{
- X#define LINESIZE 512
- X char buf[LINESIZE+1], *p;
- X char emsg[200];
- X int lineno = 0;
- X
- X while (1) {
- X if (NULL == fgets(buf, LINESIZE, fp)) /* EOF */
- X return;
- X
- X lineno++;
- X for (p=buf; *p; p++) /* skip white space */
- X if (strchr(" \t",*p) == NULL)
- X break;
- X if (*p == '\n')
- X continue;
- X
- X if (*p == '#') {
- X if (setmode(p+1)) {
- X sprintf(emsg, "Invalid pseudo comment line (%d): %s",
- X lineno, buf);
- X if (init_done)
- X dr_errmsg(emsg);
- X else
- X write(2, emsg, strlen(emsg));
- X }
- X continue;
- X }
- X /* now we expect data lines, */
- X /* initializations must be done by now */
- X if (!init_done) do_initializations();
- X
- X if (sscanf(p, informat, &x, &y) != 2) {
- X sprintf(emsg, "Invalid data line (%d): %s", lineno, buf);
- X dr_errmsg(emsg);
- X continue;
- X }
- X if (reversed) {
- X float temp = x;
- X x = y;
- X y = temp;
- X }
- X if (absolute) {
- X x = xlow + (xabs_origin + x) * (xhigh - xlow);
- X y = ylow + (yabs_origin + y) * (yhigh - ylow);
- X }
- X /* this needs to be fixed: reversed directions not handled! */
- X if (x < xlow || x > xhigh || y < ylow || y > yhigh) {
- X sprintf (emsg, "point out of range at line (%d): %s",
- X lineno, buf);
- X dr_warnmsg(emsg);
- X }
- X if (continuous) {
- X dr_goto(x, y, penup);
- X penup = 0;
- X }
- X else {
- X dr_put_mark(x, y, marker);
- X }
- X }
- X}
- X
- Xstatic void remember(to, from) /* copy string to safe place, put its */
- X /* addr into `*to' */
- Xchar **to, *from;
- X{
- X#ifndef MSDOS
- X extern char *malloc();
- X#endif
- X *to = malloc(strlen(from)+1);
- X strcpy(*to, from);
- X}
- X
- X /* handle '#<something>' lines */
- Xstatic int setmode(s) /* return 0 on success, != when trouble */
- Xchar *s;
- X{
- X for (; *s; s++) /* skip white space */
- X if (strchr(" \t",*s) == NULL)
- X break;
- X if (*s++ != '$') /* only '$' causes action */
- X return 0;
- X
- X for (; *s; s++) /* skip white space */
- X if (strchr(" \t",*s) == NULL)
- X break;
- X
- X if (!strncmp (s, "absolute", 8)) {
- X absolute = 1;
- X if (sscanf(s+8, "%f,%f", &xabs_origin, &yabs_origin) == 2)
- X return 0;
- X xabs_origin = 0.0;
- X yabs_origin = 0.0;
- X return 1;
- X }
- X
- X if (!strncmp (s, "endabsolute", 11)) {
- X absolute = 0;
- X return 0;
- X }
- X
- X if (!strncmp (s,"penup",5)) {
- X penup = 1;
- X return 0;
- X }
- X
- X
- X if (!strncmp(s, "include", 7)) {
- X FILE *fp;
- X char *p;
- X
- X for (s+=8; *s; s++) /* skip whitespace */
- X if (strchr(" \t",*s) == NULL)
- X break;
- X for (p=s; *p; p++)
- X if (strchr(" \t\n",*s) != NULL)
- X break;
- X *(p-1) = '\0'; /* put terminator */
- X
- X if (NULL == (fp = fopen(s, "r"))) {
- X perror(p);
- X return 1;
- X }
- X doit(fp); /* recursive call */
- X fclose(fp);
- X return 0;
- X }
- X
- X if (!strncmp (s, "cset", 4)) {
- X int csetnum = 0;
- X if (sscanf(s+4, "%d", &csetnum) != 1)
- X return 1;
- X if (!init_done) do_initializations();
- X dr_set_cset(csetnum);
- X return 0;
- X }
- X
- X if (!strncmp (s, "pen", 3)) {
- X if (sscanf(s+3, "%d", &pennum) != 1)
- X return 1;
- X if (!init_done) do_initializations();
- X dr_set_pen(pennum);
- X return 0;
- X }
- X
- X if (!strncmp (s, "ltype", 5)) {
- X int linetype = 1;
- X if (sscanf(s+5, "%d", &linetype) != 1)
- X return 1;
- X if (!init_done) do_initializations();
- X dr_set_ltype(linetype);
- X return 0;
- X }
- X
- X if (!strncmp(s, "mark", 4)) {
- X s += 4;
- X while (1) {
- X marker = *s++;
- X if (strchr(" \t", marker) == NULL)
- X break;
- X }
- X continuous = (strchr (" \n\r\t", marker) != NULL);
- X return 0;
- X }
- X
- X if (!strncmp(s, "date", 4)) {
- X if (dateflag)
- X return 1;
- X dateflag = 1;
- X if (init_done)
- X putdate(1);
- X return 0;
- X }
- X if (!strncmp(s, "time", 4)) {
- X if (dateflag)
- X return 1;
- X dateflag = 2;
- X if (init_done)
- X putdate(2);
- X return 0;
- X }
- X
- X if (!strncmp(s, "xlabel", 6)) {
- X if (xlabel_text) return 1;
- X s += 7; /* skip one space/separator */
- X s[strlen(s)-1] = '\0'; /* drop newline */
- X if (!init_done) {
- X remember(&xlabel_text, s);
- X return 0;
- X }
- X PUT_X_TEXT(xhigh, ylow, s);
- X xlabel_text = myname; /* some char-pointer that has non NULL */
- X /* value, so that we remember this */
- X penup = 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "ylabel", 6)) {
- X if (ylabel_text) return 1;
- X s += 7;
- X s[strlen(s)-1] = '\0';
- X if (!init_done) {
- X remember(&ylabel_text, s);
- X return 0;
- X }
- X PUT_Y_TEXT(xlow, yhigh, s);
- X ylabel_text = myname;
- X penup = 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "name", 4)) {
- X if (name_text) return 1;
- X s += 5; /* skip the space */
- X s[strlen(s)-1] = '\0'; /* drop newline */
- X if (!init_done) {
- X remember(&name_text, s);
- X return 0;
- X }
- X PUT_N_TEXT((xhigh+xlow)/2.0, yhigh, s);
- X name_text = myname;
- X penup = 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "xrange", 6)) {
- X if (sscanf(s+6, "%f,%f,%f", &xlow, &xincr, &xhigh) != 3)
- X return 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "yrange", 6)) {
- X if (sscanf(s+6, "%f,%f,%f", &ylow, &yincr, &yhigh) != 3)
- X return 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "area", 4)) {
- X if (sscanf(s+4, "%f,%f,%f,%f",
- X &xlowl, &ylowl, &xhighr, &yhighr) != 4)
- X return 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "grid", 4)) {
- X if (sscanf(s+4, "%d,%d", &xgrid_n, &ygrid_n) != 2)
- X return 1;
- X return 0;
- X }
- X
- X if (!strncmp(s, "noaxes", 6)) {
- X no_axes++;
- X return 0;
- X }
- X
- X if (!strncmp(s, "init", 4)) {
- X if (!init_done) do_initializations();
- X return 0;
- X }
- X
- X if (!strncmp(s, "size", 4)) {
- X if (sscanf(s+4, "%f", &text_size) != 1)
- X return 1;
- X if (init_done)
- X dr_set_size(text_size);
- X return 0;
- X }
- X
- X if (!strncmp(s, "shape", 5)) {
- X if (sscanf(s+5, "%f", &text_shape) != 1)
- X return 1;
- X if (init_done)
- X dr_set_shape(text_shape);
- X return 0;
- X }
- X
- X if (!strncmp(s, "direction", 9)) {
- X float xx;
- X
- X if (sscanf(s+9, "%f", &xx) != 1)
- X return 1;
- X text_angle = xx;
- X return 0;
- X }
- X
- X if (!strncmp(s, "text", 4)) return (labelpic(s+4, 0, 0));
- X if (!strncmp(s, "alabel", 6)) return (labelpic(s+6, 0, 1));
- X if (!strncmp(s, "rlabel", 6)) return (labelpic(s+6, 1, 1));
- X
- X /* other options are errors */
- X return 1;
- X}
- X
- Xstatic int labelpic(s, rel, conn)
- Xchar *s;
- Xint rel, conn;
- X{
- X float xx, yy;
- X char *s1;
- X int old_linetype;
- X
- X if (!init_done) do_initializations();
- X
- X old_linetype = dr_set_ltype(7); /* set solid line */
- X xx = strtod(s, &s1);
- X if (s1 == s) return 1;
- X s = s1+1;
- X yy = strtod(s, &s1);
- X if (s1 == s) return 1;
- X s1++; /* skip the separator */
- X s1[strlen(s1)-1] = '\0';
- X if (rel) {
- X xx += x;
- X yy += y;
- X }
- X PUT_TEXT(xx, yy, 0.0, 0.15, s1);
- X if (conn) {
- X dr_goto(xx, yy, 0);
- X dr_goto(x, y, 0);
- X dr_draw_circle();
- X }
- X else
- X penup = 1;
- X (void) dr_set_ltype(old_linetype);
- X return 0;
- X}
- X
- Xint putdate(flag)
- Xint flag;
- X{
- X struct tm *timp;
- X long clk;
- X char buf1[40], buf2[20];
- X
- X if (time(&clk) < 0) {
- X (void) sprintf (buf1, "time() failed.");
- X (void) dr_errmsg(buf1);
- X return 1;
- X }
- X timp = localtime(&clk);
- X sprintf(buf1, "%d/%d/%d",
- X timp->tm_mday, timp->tm_mon+1, timp->tm_year + 1900);
- X if (flag > 1)
- X sprintf(buf2, " %02d:%02d:%02d",
- X timp->tm_hour, timp->tm_min, timp->tm_sec);
- X else
- X buf2[0] = '\0';
- X strcat(buf1, buf2);
- X PUT_TEXT(xhigh, yhigh, -(float)strlen(buf1), 0.7, buf1);
- X penup = 1;
- X return 0;
- X}
- X
- X
- Xvoid fatal(s1, s2)
- Xchar *s1, *s2;
- X{
- X fprintf (stderr,"%s: Fatal error: %s %s\n", myname, s1, s2);
- X exit(1);
- X}
- X
- Xstatic char *utbl[] = {
- X "-a xlo,ylo,xhi,yhi\tspecify relative plot area on paper",
- X "-b\t\t\tdon't draw axes",
- X "-c num\t\t\tchoose character set `num'",
- X "-d\t\t\tinclude date (time) stamp",
- X "-f c1,c2\t\tuse these columns of input, higher is for y",
- X "-g xgrid,ygrid\t\tspecify x&y grids",
- X "-h\t\t\tgive this stuff",
- X "-l\t\t\tlinetype",
- X "-m marker\t\tspecify marker & discontinous mode",
- X "-n text\t\tname the picture",
- X "-p num\t\t\tspecify pen number",
- X#ifdef GL_LIB
- X "-t target\t\tspecify device: `ega', `a3', `a4' etc. Defaults from env.",
- X#else
- X "-t target\t\tspecify device: `a3', `a4' etc. Defaults from env.",
- X#endif
- X "-x|y low,incr,high\tspecify axis range",
- X "-X|Y text\t\taxis label",
- X "-v\t\t\tprint version ID",
- X "Most (all?) of these may also be given inside the data, look for manual",
- X NULL
- X};
- X
- Xvoid usage()
- X{
- X register char **p;
- X printf ("usage: \"%s [opts] [file ...]\"\n", myname);
- X for (p=utbl; *p; p++)
- X (void)printf (" %s\n", *p);
- X exit(0);
- X}
- END_OF_FILE
- if test 17080 -ne `wc -c <'draw.c'`; then
- echo shar: \"'draw.c'\" unpacked with wrong size!
- fi
- # end of 'draw.c'
- fi
- echo shar: End of archive 2 \(of 2\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-